package logic

import (
	"cld-quick-cli/dao"
	"cld-quick-cli/database/keys"
	"cld-quick-cli/database/models"
	"cld-quick-cli/pkg"
	"cld-quick-cli/router/parameters"
	"cld-quick-cli/setup"
	"errors"
	"github.com/go-redis/redis"
	"time"
)

// SendNewPostLogic 发送新的帖子的业务逻辑
func SendNewPostLogic(post *parameters.SendNewPostParams) error {
	// 1. 先检查帖子的title是不是重复了！
	err := dao.CheckPostExistByTitle(post.Title)
	if err != nil {
		return errors.New("帖子重复了！")
	}
	// 2.如果没有重复则新建！
	postId := pkg.GenSnowflakeID()
	err = dao.InsertNewPost(postId, post)
	if err != nil {
		return errors.New("帖子创建失败！！")
	}
	//3. 把帖子创建时间存入redis !
	setup.RedisDB.ZAdd(keys.KeyPostTimeZSet, redis.Z{
		Score:  float64(time.Now().Unix()),
		Member: postId,
	})
	return nil
}

// GetPostDetailsLogic 帖子详情业务逻辑
func GetPostDetailsLogic(postId string) (*models.PostDetailsModel, error) {
	var postDetails = new(models.PostDetailsModel)
	// 1. 拿到帖子的详情
	errMsg := "查询帖子详情失败"
	post, err := dao.GetPostDetailsById(postId)
	if err != nil {
		return nil, errors.New(errMsg)
	}
	// 2.拿社区的详情
	community, err := dao.GetCommunityDetailsByCommunityId(&post.CommunityId)
	if err != nil {
		return nil, errors.New(errMsg)
	}
	// 拼凑数据返回！
	postDetails.PostModel = *post
	postDetails.CommunityModel = *community
	return postDetails, nil
}

// GetPostListByFilterParamsLogic 分页查询帖子业务逻辑
func GetPostListByFilterParamsLogic(params *parameters.GetPostListByFilterParams) (*models.CommonListModel[[]models.PostDetailsModel], error) {
	count, err := dao.GetPostListCountByFilterParams(params)
	if err != nil {
		return nil, err
	}
	postLists, err := dao.GetPostListByFilterParams(params)
	if err != nil {
		return nil, err
	}
	clm := models.CommonListModel[[]models.PostDetailsModel]{
		Total:             &count,
		List:              postLists,
		CurrentPageNumber: &params.PageNumber,
		CurrentPageSize:   &params.PageSize,
	}
	return &clm, nil
}

// VotePostLogic 投票业务逻辑
/*
投一票就加432分 86400/200 -> 200张赞成票可以给你的贴子续一天 -> 《redis实战》
	投票的几种情况:
	direction=1时，有两种情况:
		1。之前没有投过票，现在投赞成票		  0>1 = (1-0)* 432   = 432
		2，之前投反对票，现在改投赞成票		 -1>1 = (1-(-1))*432 = 864
	direction=0时，有两种情况:
		1，之前投过费成票，现在要取消投票    1>0 = (0-1)*432 = -432
		2。之前投过反对票，现在要取消投票    0>1 = (1-0)*432 = 432
	direction=-1时，有两种情况:
		1，之前没有投过票，现在投反对票   	0>-1 = (-1-0)*432 = -432
		2，之前投费成票，现在改投反对票   	1->-1 = (-1-1)*432 = -864
【总结公式：(目标值-初始值) * 分数】
	投票的限制:
	每个贴子自发表之日起一个星期之内允许用户投票，超过一个星期就不允许再投票了
	1，到期之后将redis中保存的赞成票数及反对票数存储到mysql表中
	2，到期之后删除那个 KeyPostVotedSetPF
	本项目使用简化版的投票分数
*/
func VotePostLogic(params *parameters.VotePostParams) error {
	// 1.首先判断传过来的帖子id是不是存在！去redis查 如果存在则返回时间戳！
	postTime, err := dao.GetPostIdExistFromRedis(params.PostId)
	if err != nil {
		return errors.New("帖子不存在了！")
	}
	// 2.判断帖子是不是超过了最长地投票期限！只能投当天的帖子
	i := time.Now().Unix() - int64(postTime) // 发帖时间距离现在的时间 单位 s
	if i > 60*60 {                           // 半小时内的！
		return errors.New("投票时间已过！")
	}
	// 3. 进入验证！
	err = dao.UserVotePost(params)
	if err != nil {
		return errors.New("投票失败！")
	}
	// 3.获取当前用户对这篇帖子的状态 0 -1 0 然后根据公式计算分数加到帖子分数上！
	return nil
}

func UpdatePostLogic(post *parameters.UpdatePostParams) error {
	// 1. 先检查帖子的title是不是重复了！
	//err := dao.CheckPostExistByTitle(post.Title)
	//if err != nil {
	//	return errors.New("帖子重复了！")
	//}
	// 2. 没有重复则更新
	err := dao.UpdateNewPost(post)
	if err != nil {
		return errors.New("帖子更新失败！")
	}
	return nil
}
